if (HAVE_MALCONTENT) {
({default: Malcontent} = await import('gi://Malcontent?version=0'));
Gio._promisify(Malcontent.Manager.prototype, 'get_app_filter_async');
+ Gio._promisify(Malcontent.Manager.prototype, 'get_session_limits_async');
}
+// We require libmalcontent ≥ 0.14.0 for session limits
+const HAVE_MALCONTENT_0_14 = Malcontent &&
+ GObject.signal_lookup('session-limits-changed', Malcontent.Manager) > 0;
+
let _singleton = null;
/**
const ParentalControlsManager = GObject.registerClass({
Signals: {
'app-filter-changed': {},
+ 'session-limits-changed': {},
},
}, class ParentalControlsManager extends GObject.Object {
_init() {
this._initialized = false;
this._disabled = false;
this._appFilter = null;
+ this._sessionLimits = null;
this._initializeManager();
}
console.debug('Skipping parental controls support, malcontent not found');
this._initialized = true;
this.emit('app-filter-changed');
+ this.emit('session-limits-changed');
return;
}
const connection = await Gio.DBus.get(Gio.BusType.SYSTEM, null);
this._manager = new Malcontent.Manager({connection});
this._appFilter = await this._getAppFilter();
+
+ if (HAVE_MALCONTENT_0_14)
+ this._sessionLimits = await this._getSessionLimits();
} catch (e) {
logError(e, 'Failed to get parental controls settings');
return;
}
this._manager.connect('app-filter-changed', this._onAppFilterChanged.bind(this));
+ if (HAVE_MALCONTENT_0_14)
+ this._manager.connect('session-limits-changed', this._onSessionLimitsChanged.bind(this));
// Signal initialisation is complete.
this._initialized = true;
this.emit('app-filter-changed');
+ this.emit('session-limits-changed');
}
async _getAppFilter() {
}
}
+ async _getSessionLimits() {
+ let sessionLimits = null;
+
+ try {
+ sessionLimits = await this._manager.get_session_limits_async(
+ Shell.util_get_uid(),
+ Malcontent.ManagerGetValueFlags.NONE,
+ null);
+ } catch (e) {
+ if (!e.matches(Malcontent.ManagerError, Malcontent.ManagerError.DISABLED))
+ throw e;
+
+ console.debug('Parental controls globally disabled');
+ this._disabled = true;
+ }
+
+ return sessionLimits;
+ }
+
+ async _onSessionLimitsChanged(manager, uid) {
+ // Emit 'changed' signal only if session-limits are changed for currently logged-in user
+ const currentUid = Shell.util_get_uid();
+ if (currentUid !== uid)
+ return;
+
+ try {
+ this._sessionLimits = await this._getSessionLimits();
+ this.emit('session-limits-changed');
+ } catch (e) {
+ // Keep the old session limits
+ logError(e, `Failed to get new MctSessionLimits for uid ${Shell.util_get_uid()} on session-limits-changed`);
+ }
+ }
+
get initialized() {
return this._initialized;
}
return this._appFilter.is_appinfo_allowed(appInfo);
}
+
+ /**
+ * Check whether parental controls session limits are enabled for the account,
+ * and if the library supports the features required for the functionality.
+ *
+ * @returns {bool} whether session limits are supported and enabled.
+ */
+ sessionLimitsEnabled() {
+ // Are latest parental controls enabled (at configure or runtime)?
+ if (!HAVE_MALCONTENT_0_14 || this._disabled)
+ return false;
+
+ // Have we finished initialising yet?
+ if (!this.initialized) {
+ console.debug('Ignoring session limits because parental controls not yet initialised');
+ return false;
+ }
+
+ return this._sessionLimits.is_enabled();
+ }
});